#include "ChunkManager.h"
#include "base.h"
#include "Types.h"

ChunkManager::ChunkManager(void)
{
	m_pViewerEntity = NULL;
	m_bForcedChunkUpdate = true;
}
ChunkManager::~ChunkManager(void)
{
}
bool ChunkManager::Initialize(Entity *pViewerEntity, uint chunkViewDist)
{
	m_pViewerEntity = pViewerEntity;
	m_nChunkViewRange = chunkViewDist;
	m_chunkUpdateTimer.Start();
	m_bForcedChunkUpdate = true;
	return true;
}
void ChunkManager::Update()
{
	long msTime = m_chunkUpdateTimer.GetTimeRunningDuration().total_milliseconds();
	if(m_bForcedChunkUpdate)
	{
		m_bForcedChunkUpdate = false;
		UpdateChunkCache();
		m_chunkUpdateTimer.Start();
	}else if(msTime > CHUNK_UPDATE_TIME_MS) {
		UpdateChunkCache();
		m_chunkUpdateTimer.Start();
	}
}
void ChunkManager::UpdateChunkCache()
{
	//Temporarily a Load-Only ChunkManager
	Rect loadRect = GetPlayerLoadRectangle();
	int loadXStart = (int)loadRect.X();
	int loadZStart = (int)loadRect.Y();
	int loadXMax = loadXStart + (int)loadRect.W();
	int loadZMax = loadZStart + (int)loadRect.H();

	m_chunksToDraw.clear();

	ChunkMap::iterator it;//X-Order
	ChunkInnerMap::iterator itInner;//Z-Order
	for(int x = loadXStart; x < loadXMax; x++)
	{
		it = m_chunkMap.find(x);
		if(it == m_chunkMap.end())
		{
			m_chunkMap[x] = ChunkInnerMap();
			for(int z = loadXStart; z < loadZMax; z++)
			{
				//Creat new chunks for this z-Row
				Chunk *pNewChunk = m_chunkMap[x][z] = new Chunk(this, x, z);
				pNewChunk->Generate();
				m_chunksToDraw.push_back(pNewChunk);
			}
		}else{
			for(int z = loadXStart; z < loadZMax; z++)
			{
				itInner = m_chunkMap[x].find(z);
				if(itInner == m_chunkMap[x].end())
				{
					//Create new chunk for this x-z location
					Chunk *pNewChunk = m_chunkMap[x][z] = new Chunk(this, x, z);
					pNewChunk->Generate();
					m_chunksToDraw.push_back(pNewChunk);
				}else{
					m_chunksToDraw.push_back(m_chunkMap[x][z]);
				}
			}
		}
	}
}
Rect ChunkManager::GetPlayerLoadRectangle()
{
	vector3 playerPos = m_pViewerEntity->GetPosition();
	int playerChunkPosX = (int)playerPos.x - ((int)playerPos.x % Chunk::xBlocks);
	int playerChunkPosZ = (int)playerPos.z - ((int)playerPos.z % Chunk::zBlocks);
	return Rect(playerChunkPosX - (int)m_nChunkViewRange, playerChunkPosZ - (int)m_nChunkViewRange,
		m_nChunkViewRange*2, m_nChunkViewRange*2);
}